package com.compty.core.framework.image;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.compty.core.framework.util.StringUtil;
import com.compty.core.struts2.BaseAction;
import com.compty.paint.util.ImageUtil;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

// 图片操作，改变大小加水印  
public final class ImageUtils {
	
    /** * 日志. */
    private static Log logger = LogFactory.getLog(BaseAction.class);

	/**
	 * 给图片加水印，但不改变大小
	 * 
	 * @param strOriginalFileName
	 *            String(原始文件) 就是水印原始文件
	 * @param strWaterMarkFileName
	 *            String(水印文件)
	 */
	public void waterMark(String strOriginalFileName, String strWaterMarkFileName) {
		try {
			// 源文件
			File fileOriginal = new File(strOriginalFileName);
			Image imageOriginal = ImageIO.read(fileOriginal);
			int widthOriginal = imageOriginal.getWidth(null);
			int heightOriginal = imageOriginal.getHeight(null);
			logger.info("widthOriginal:" + widthOriginal+ "theightOriginal:" + heightOriginal);
			BufferedImage bufImage = new BufferedImage(widthOriginal,
					heightOriginal, BufferedImage.TYPE_INT_RGB);
			Graphics g = bufImage.createGraphics();
			g.drawImage(imageOriginal, 0, 0, widthOriginal, heightOriginal,
					null);
			// 水印文件
			File fileWaterMark = new File(strWaterMarkFileName);
			Image imageWaterMark = ImageIO.read(fileWaterMark);
			int widthWaterMark = imageWaterMark.getWidth(null);
			int heightWaterMark = imageWaterMark.getHeight(null);
			logger.info("widthWaterMark:" + widthWaterMark+ "theightWaterMark:" + heightWaterMark);
			// 水印文件在源文件的右下角
			g.drawImage(imageWaterMark, widthOriginal - widthWaterMark,heightOriginal - heightWaterMark, widthWaterMark,
					heightWaterMark, null);
			g.dispose();
			FileOutputStream fos = new FileOutputStream(strOriginalFileName);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
			encoder.encode(bufImage);
			fos.flush();
			fos.close();
			fos = null;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	 /** *//**
     * 缩放图像
     * @param srcImageFile 源图像文件地址
     * @param destPath       缩放后的图像地址
     * @param scale        缩放比例
     * @param flag         缩放选择:true 放大; false 缩小;
     */
    public static void scale(String srcImageFile, String destPath, float scale)
      {
        try
        {
            BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
            int width = src.getWidth(); // 得到源图宽
            int height = src.getHeight(); // 得到源图长
            
            // 放大
            width = (int)(width * scale);
            height = (int)(height * scale);
          
            Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            ImageIO.write(tag, "JPEG", new File(destPath));// 输出到文件流
        }
        catch (IOException e)
           {
            e.printStackTrace();
        }
    }

    /** *//**
     * 图像切割
     * @param srcImageFile 源图像地址
     * @param descDir      切片目标文件夹
     * @param destWidth    目标切片宽度
     * @param destHeight   目标切片高度
     */
    public static void cut(String srcImageFile, String descDir, int destWidth, int destHeight)
    {
        try
        {
            Image img;
            ImageFilter cropFilter;
            // 读取源图像
            BufferedImage bi = ImageIO.read(new File(srcImageFile));
            int srcWidth = bi.getHeight(); // 源图宽度
            int srcHeight = bi.getWidth(); // 源图高度
            if (srcWidth > destWidth && srcHeight > destHeight)
            {
                Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
                destWidth = 200; // 切片宽度
                destHeight = 150; // 切片高度
                int cols = 0; // 切片横向数量
                int rows = 0; // 切片纵向数量
                // 计算切片的横向和纵向数量
                if (srcWidth % destWidth == 0)
                {
                    cols = srcWidth / destWidth;
                }
                else
                {
                    cols = (int) Math.floor(srcWidth / destWidth) + 1;
                }
                if (srcHeight % destHeight == 0)
                {
                    rows = srcHeight / destHeight;
                }
                else
                {
                    rows = (int) Math.floor(srcHeight / destHeight) + 1;
                }
                // 循环建立切片
                // 改进的想法:是否可用多线程加快切割速度
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        // 四个参数分别为图像起点坐标和宽高
                        // 即: CropImageFilter(int x,int y,int width,int height)
                        cropFilter = new CropImageFilter(j * 200, i * 150, destWidth, destHeight);
                        img = Toolkit.getDefaultToolkit().createImage(
                                        new FilteredImageSource(image.getSource(), cropFilter));
                        BufferedImage tag = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
                        Graphics g = tag.getGraphics();
                        g.drawImage(img, 0, 0, null); // 绘制缩小后的图
                        g.dispose();
                        // 输出为文件
                        ImageIO.write(tag, "JPEG", new File(descDir + "pre_map_" + i + "_" + j + ".jpg"));
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /** *//**
     * 图像类型转换 GIF->JPG GIF->PNG PNG->JPG PNG->GIF(X)
     */
    public static void convert(String source, String result)
    {
        try
        {
            File f = new File(source);
            f.canRead();
            f.canWrite();
            BufferedImage src = ImageIO.read(f);
            ImageIO.write(src, "JPG", new File(result));
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /** *//**
     * 彩色转为黑白
     * @param source
     * @param result
     */
    public static void gray(String source, String result)
    {
        try
        {
            BufferedImage src = ImageIO.read(new File(source));
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            src = op.filter(src, null);
            ImageIO.write(src, "JPEG", new File(result));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
    /**    
     * 对图片裁剪，并把裁剪完蛋新图片保存 。  
     * @param srcpath 源图片路径名称
     * @param subpath 剪切图片存放路径名称
     * @param x 剪切点x坐标
     * @param y 剪切点y坐标
     * @param width 剪切点宽度
     * @param height 剪切点高度
     * 
   */    
     public static void  cut(String srcpath,String subpath ,int  x,int  y,int  width ,int  height)  throws  IOException {    
            
        FileInputStream is  =   null  ;   
        ImageInputStream iis  = null  ;  
      //这个是获取图片扩展名的方法，比如：jpg。
        String imgType = StringUtil.getExt(srcpath);   
        
         try {      
             // 读取图片文件    
            is  =   new  FileInputStream(srcpath);    
               
            /*   
             * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader   
             * 声称能够解码指定格式。 参数：formatName - 包含非正式格式名称 .  
             *（例如 "jpeg" 或 "tiff"）等 。   
         */    
            Iterator <ImageReader>  it  =  ImageIO.getImageReadersByFormatName(imgType);     
            ImageReader reader  =  it.next();    
             // 获取图片流     
            iis  =  ImageIO.createImageInputStream(is);   
                  
            /*    
             * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。  
             * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader  
             *  避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。  
         */    
            reader.setInput(iis, true ) ;   
               
            /*    
             * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O   
             * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件  
             * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回   
             * ImageReadParam 的实例。    
        */    
            ImageReadParam param  =  reader.getDefaultReadParam();    
                
            /*   
             * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象  
             * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。   
        */     
            Rectangle rect  =   new  Rectangle(x, y, width, height);    
               
                 
             // 提供一个 BufferedImage，将其用作解码像素数据的目标。     
            param.setSourceRegion(rect);
//            param.setSourceBands(sourceBands)
 
            /*   
             * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将  
             * 它作为一个完整的 BufferedImage 返回。  
              */    
            BufferedImage bi  =  reader.read(0,param);                   
         
             // 保存新图片     
            ImageIO.write(bi,imgType,  new  File(subpath));     
            
        }  finally {   
             if (is != null )   
               is.close() ;
             if (iis != null )   
               iis.close();     
        }     
    }   
     
     /**
      *@Todo:检查图片尺寸是否合格
      *@CreateTime:2011-9-8 下午05:49:17
      * @param srcpath 图片路径
      * @param sharpId 图片形状
     * @throws IOException 
      */
     public static String  checkImageSharp(String srcpath,String sharpId) throws IOException{
    	 
 		File f = new File(srcpath);
		BufferedImage sourceImage = ImageIO.read(f);
		
		int prevW = sourceImage.getWidth();
        int prevH = sourceImage.getHeight();
        String flag = null ;
        if(prevW >= prevH){
        	if((prevW*1.0)/prevH > 1.2){
        		if(!"3".equals(sharpId) && !"4".equals(sharpId)){
        			flag = "2";
        		}
        	}else{
        		if(!"1".equals(sharpId)){
        			flag = "1";
        		}
        	}
        }else{
        	if((prevH*1.0)/prevW > 1.2){
        		if(!"2".equals(sharpId) && !"5".equals(sharpId)){
        			flag = "3";
        		}
        	}else{
        		if(!"1".equals(sharpId)){
        			flag = "1";
        		}
        	}
        }
        
        return flag;
     }
     
     /**    
      * 对图片缩放，并把裁剪完蛋新图片保存 。  
      * @param srcpath 源图片路径名称
      * @param subpath 剪切图片存放路径名称
      * @param sharpId 形状编号
      * sharpId 1:表示正方形 2：表示长方形(竖),3：表示长方形(横),4：表示长卷(横披),5:长卷(立轴),6:表示头像,7:表示展览海报
	 * 8:表示背景摆设  9:表示画廊logo 10:表示拍卖画册封面
    */     
	 public  static String  scaleImage(String srcpath,String subpath,Long sharpId) throws Exception {
		
		File f = new File(srcpath);
		BufferedImage sourceImage = ImageIO.read(f);
		
		int prevW = sourceImage.getWidth();
        int prevH = sourceImage.getHeight();
        String flag = "0" ;
        if(prevW >= prevH){
        	if((prevW*1.0)/prevH > 1.2){
        		flag = "2";
        	}else{
        		flag = "1";
        	}
        }else{
        	if((prevH*1.0)/prevW > 1.2){
        		flag = "3";
        	}else{
        		flag = "1";
        	}
        }
		
		double ratio = 0.0;
		int maxNumber = prevW > prevH ? prevW: prevH; //取长宽中较大的数
		if(sharpId == 1){//正方形
			
			if( (prevW*1.0)/prevH > 1.2 || (prevH*1.0)/prevW > 1.2){
				return flag;
			}
			
			if(maxNumber <= 900) return null;
			
			ratio = new BigDecimal(900.00/maxNumber).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
		}
		else if(sharpId == 2){//长方形(竖)
			
			if(prevW > prevH){
				return flag;
			}
			
			if(prevW <= 900) return null;
			
			ratio = new BigDecimal(900.00/prevW).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
		}
		else if(sharpId == 3){//长方形(横)
			
			if(prevW < prevH){
				return flag;
			}
			
			if(prevW <= 900) return null;
			
			ratio = new BigDecimal(900.00/prevW).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
		}
		else if(sharpId == 4){//长卷(横披)
			
			if(prevW < prevH){
				return flag;
			}
			
			if(maxNumber <= 1000) return null;
			
			ratio = new BigDecimal(1000.00/maxNumber).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
		}
		else if(sharpId == 5){//长卷(立轴)
			
			if(prevW > prevH){
				return flag;
			}
			if(maxNumber <= 1000) return null;
			
			ratio = new BigDecimal(1000.00/maxNumber).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
		}
		else if(sharpId == 6){//头像
				
				if(maxNumber <= 362) return null;
				
				ratio = new BigDecimal(362.00/maxNumber).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
				
				ImageUtil.resize(srcpath,subpath, (int)(prevW*ratio), (int)(prevH*ratio));
				
				return null;
			}
			else if(sharpId == 7){//展览
				
				if(prevW > prevH){
					return flag;
				}
				if(maxNumber <= 414) return null;
				
				ratio = new BigDecimal(414.00/maxNumber).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
				ImageUtil.resize(srcpath,subpath, (int)(prevW*ratio), (int)(prevH*ratio));
				return null;
			}
			else if(sharpId == 9){

				if(maxNumber <= 217) return null;
				
				ratio = new BigDecimal(217.00/maxNumber).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
				ImageUtil.resize(srcpath,subpath,(int)(prevW*ratio), (int)(prevH*ratio));
				return null;
			}else{
				ratio = 1.0;
			}
			
			ImageUtil.resize(srcpath,subpath, (int)(prevW*ratio), (int)(prevH*ratio));
		
		return null;
	}
	
	/**
	 *@CreateTime:2011-11-2 下午02:54:37
	 * @param srcpath 源图片路径
	 * @param subpath 目标图片路径
	 * @param targetWidth 目标图片宽
	 * @param targetHeight 目标图片高
	 * @throws Exception
	 */
	public  static void  scaleImage(String srcpath,String subpath,double targetWidth,double targetHeight) throws Exception {
		
		String imgType = StringUtil.getExt(srcpath);   
		File f = new File(srcpath);
		BufferedImage sourceImage = ImageIO.read(f);
		
		int prevW = sourceImage.getWidth();
        int prevH = sourceImage.getHeight();
        
    	double ratio = 1.0;
        if(targetWidth >0 ){
        	if(prevW > targetWidth){
        		ratio = new BigDecimal(targetWidth/prevW).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
        	}
        }
        else if( targetHeight >0 ){
        	if(prevH > targetHeight){
        		ratio = new BigDecimal(targetHeight/prevH).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
        	}
        }
        
		AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
		BufferedImage dstImage  = op.filter(sourceImage, null);
		try {
			ImageIO.write( dstImage, imgType, new File(subpath));
		} catch (Exception ex) {
			throw new Exception(" ImageIo.write error in CreatThum.: "
					+ ex.getMessage());
		}
		
	}


	public static void main(String[] args) throws IOException {
		
//		cut("C:\\Documents and Settings\\Administrator\\My Documents\\艺术交易\\会议室2.jpg", "c:/a.jpg", 10, 20, 200, 300);
		cut("C:\\20107302050751629.gif", "c:\\22.gif", 10, 20, 200, 300);
		
	}

}
